package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.model.album.TrackOrderVo;
import com.atguigu.tingshu.model.user.UserInfo;
import com.atguigu.tingshu.model.user.UserPaidTrack;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

    @Autowired
    private TrackInfoMapper trackInfoMapper;

    @Autowired
    private VodService vodService;

    @Autowired
    private AlbumInfoMapper albumInfoMapper;

    @Autowired
    private AlbumInfoService albumInfoService;

    @Autowired
    private TrackStatMapper trackStatMapper;

    @Resource
//    @Qualifier(value = "userInfoFeignClient")
    private UserInfoFeignClient userInfoFeignClient;

    @Override
    public void saveTrackInfo(TrackInfoVo trackInfoVo) {
        //保存声音信息
        TrackInfo trackInfo = new TrackInfo();
        BeanUtils.copyProperties(trackInfoVo, trackInfo);
        Long userId = AuthContextHolder.getUserId();
        userId = userId == null ? 1L : userId;
        trackInfo.setUserId(userId);
        //orderNum需要在原有最大值的基础+1
        TrackInfo dbTrackInfo = this.getOne(new LambdaQueryWrapper<TrackInfo>().eq(TrackInfo::getAlbumId, trackInfoVo.getAlbumId())
                .orderByDesc(TrackInfo::getOrderNum).last("limit 1").select(TrackInfo::getOrderNum));

        trackInfo.setOrderNum(dbTrackInfo == null ? 1 : dbTrackInfo.getOrderNum() + 1);

        //获取media信息
        TrackMediaInfoVo mediaInfo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
        if (mediaInfo != null) {
            trackInfo.setMediaDuration(new BigDecimal(mediaInfo.getDuration()));
            trackInfo.setMediaUrl(mediaInfo.getMediakUrl());
            trackInfo.setMediaSize(mediaInfo.getSize());
            trackInfo.setMediaType(mediaInfo.getType());
        }
        //设置来源
        trackInfo.setSource(SystemConstant.TRACK_SOURCE_USER);
        //设置审核状态
        trackInfo.setStatus(SystemConstant.TRACK_STATUS_PASS);
        this.save(trackInfo);
        Long trackId = trackInfo.getId();
        //保存专辑表
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfoVo.getAlbumId());
        if (albumInfo != null) {
            albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() + 1);
        }
        albumInfoMapper.updateById(albumInfo);
        //保存声音统计信息
        initTrackStat(trackId, SystemConstant.TRACK_STAT_PLAY);
        initTrackStat(trackId, SystemConstant.TRACK_STAT_COLLECT);
        initTrackStat(trackId, SystemConstant.TRACK_STAT_PRAISE);
        initTrackStat(trackId, SystemConstant.TRACK_STAT_COMMENT);
    }

    private void initTrackStat(Long trackId, String type) {
        TrackStat trackStat = new TrackStat();
        trackStat.setTrackId(trackId);
        trackStat.setStatType(type);
        trackStat.setStatNum(0);
        trackStatMapper.insert(trackStat);
    }

    @Override
    public IPage<TrackListVo> findUserTrackPage(Integer page, Integer limit, TrackInfoQuery query) {
        IPage<TrackListVo> pages = new Page<>(page, limit);
        Long userId = AuthContextHolder.getUserId();
        userId = userId == null ? 1L : userId;
        query.setUserId(userId);
        return trackInfoMapper.findUserTrackPage(pages, query);
    }


    @Override
    public void updateTrackInfo(Long trackId, TrackInfoVo trackInfoVo) {
        //更新声音信息表
        TrackInfo trackInfo = new TrackInfo();
        BeanUtils.copyProperties(trackInfoVo, trackInfo);
        trackInfo.setId(trackId);
        //更新视频的信息
        TrackMediaInfoVo mediaInfo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
        if (mediaInfo != null) {
            trackInfo.setMediaDuration(new BigDecimal(mediaInfo.getDuration()));
            trackInfo.setMediaUrl(mediaInfo.getMediakUrl());
            trackInfo.setMediaSize(mediaInfo.getSize());
            trackInfo.setMediaType(mediaInfo.getType());
        }
        this.updateById(trackInfo);
    }

    @Override
    public void removeTrackInfo(Long trackId) {
        //查询声音信息
        TrackInfo trackInfo = this.getById(trackId);
        //删除声音表信息
        this.removeById(trackId);
        //删除声音统计表信息
        trackStatMapper.delete(new LambdaUpdateWrapper<TrackStat>().eq(TrackStat::getTrackId, trackId));
        //修改专辑表的包含声音数-1
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
        albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() - 1);
        albumInfoMapper.updateById(albumInfo);
        //删除云点播视频
        vodService.removeMedia(trackInfo.getMediaFileId());
    }

    @Override
    public Page<AlbumTrackListVo> findAlbumTrackPage(Long albumId, Integer page, Integer limit) {
        //分页查询声音列表
        Page<AlbumTrackListVo> pages = new Page<>(page, limit);
        Page<AlbumTrackListVo> trackPage = this.trackInfoMapper.findAlbumTrackPage(pages, albumId);
        //1.如果为空，直接返回
        List<AlbumTrackListVo> trackList = trackPage.getRecords();
        if (CollectionUtils.isEmpty(trackList)) {
            return trackPage;
        }
        //2.根据albumId查询专辑表
        AlbumInfo albumInfo = albumInfoService.getAlbumInfo(albumId);
        Assert.notNull(albumInfo, "分页查询声音列表时：获取专辑信息失败！");
        //专辑支付类型 免费直接返回
        if (SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfo.getPayType())) {
            return trackPage;
        }
        //3.专辑付类型不免费 过滤需要付费声音
        List<AlbumTrackListVo> payTrackList = trackList.stream().filter(track -> track.getOrderNum() > albumInfo.getTracksForFree()).collect(Collectors.toList());
        //不存在收费声音
        if (CollectionUtils.isEmpty(payTrackList)) {
            return trackPage;
        }
        //4.根据userId查询用户信息
        Long userId = AuthContextHolder.getUserId();
        if (userId != null) {
            Result<UserInfo> userResult = userInfoFeignClient.findUserById(userId);
            Assert.notNull(userResult, "分页查询声音列表时：获取用户信息失败！");
            UserInfo userInfo = userResult.getData();
            Assert.notNull(userInfo, "分页查询声音列表时：获取用户信息失败");
            //如果专辑付费类型 vip免费且用户是VIP 直接返回
            if (userInfo.getIsVip() == 1 && SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(albumInfo.getPayType())
                    && userInfo.getVipExpireTime().after(new Date())) {
                return trackPage;
            }
            //根据userId和albumId查询 user_paid_album表 是否购买专辑
            Result<Boolean> payAlbumResult = userInfoFeignClient.findPayAlbum(albumId);
            Assert.notNull(payAlbumResult, "分页查询声音列表时：获取已购买专辑信息失败！");
            Boolean isPay = payAlbumResult.getData();
            if (isPay) {
                return trackPage;
            }
            //6.根据trackId 和 userId 查询 user_paid_track表 是否购买声音
            Result<List<UserPaidTrack>> payTrackResult = userInfoFeignClient.findPayTrack(albumId);
            Assert.notNull(payTrackResult, "分页查询声音列表时：获取购买声音信息失败！");
            List<UserPaidTrack> payTrack = payTrackResult.getData();
            if (CollectionUtils.isEmpty(payTrack)) {
                payTrackList.forEach(track -> track.setIsShowPaidMark(true));
                return trackPage;
            }
            //声音购买不为空
            List<Long> payIds = payTrack.stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
            payTrackList.forEach(track -> {
                if (!payIds.contains(track.getTrackId())) {
                    track.setIsShowPaidMark(true);
                }
            });
        } else {
            payTrackList.forEach(track -> track.setIsShowPaidMark(true));
        }
        return trackPage;
    }

    @Override
    public TrackStatVo getTrackStatVo(Long trackId) {
        return this.trackStatMapper.getTrackStatVo(trackId);
    }

    @Override
    public List<TrackOrderVo> findUserTrackPaidList(Long trackId) {
        //根据trackId查询当前声音
        TrackInfo trackInfo = this.getById(trackId);
        //判断是否为空
        if (trackInfo == null) {
            throw new GuiguException(ResultCodeEnum.ILLEGAL_REQUEST);
        }
        //根据albumId查询orderNum大于该声音的声音列表
        List<TrackInfo> trackInfoList = this.list(new LambdaQueryWrapper<TrackInfo>()
                .eq(TrackInfo::getAlbumId, trackInfo.getAlbumId())
                .ge(TrackInfo::getOrderNum, trackInfo.getOrderNum()));
        //查询用户购买的声音列表
        Result<List<UserPaidTrack>> payTrackResult = userInfoFeignClient.findPayTrack(trackInfo.getAlbumId());
        Assert.notNull(payTrackResult, "生成购买声音套餐时，获取已购买声音失败！");
        List<UserPaidTrack> payTrackList = payTrackResult.getData();
        //过滤需要付费列表
        List<TrackInfo> needPayTrackList = null;
        if (CollectionUtils.isEmpty(payTrackList)) {
            needPayTrackList = trackInfoList;
        } else {
            //获取已购买声音id
            List<Long> ids = payTrackList.stream().map(payTrackInfo -> payTrackInfo.getTrackId()).collect(Collectors.toList());
            needPayTrackList = trackInfoList.stream().filter(track -> !ids.contains(track.getId())).collect(Collectors.toList());
        }
        if (CollectionUtils.isEmpty(needPayTrackList)) {
            throw new GuiguException(ResultCodeEnum.ILLEGAL_REQUEST);
        }
        //查询专辑信息
        AlbumInfo albumInfo = this.albumInfoMapper.selectById(trackInfo.getAlbumId());
        //单价
        BigDecimal price = albumInfo.getPrice();
        //组装套餐
        List<TrackOrderVo> trackOrderVos = new ArrayList<>();
        //当前声音
        TrackOrderVo trackOrderVo = new TrackOrderVo();
        trackOrderVo.setTrackCount(1);
        trackOrderVo.setPrice(price);
        trackOrderVo.setName("本集");
        trackOrderVos.add(trackOrderVo);

        //需要付费的集数
        int size = needPayTrackList.size();
        if (size > 10) {
            TrackOrderVo trackOrderVoo = new TrackOrderVo();
            trackOrderVoo.setTrackCount(10);
            trackOrderVoo.setPrice(price.multiply(new BigDecimal(10)));
            trackOrderVoo.setName("后10集");
            trackOrderVos.add(trackOrderVoo);
        }

        if (size > 20) {
            TrackOrderVo trackOrderVoo = new TrackOrderVo();
            trackOrderVoo.setTrackCount(20);
            trackOrderVoo.setPrice(price.multiply(new BigDecimal(20)));
            trackOrderVoo.setName("后20集");
            trackOrderVos.add(trackOrderVoo);
        }

        if (size > 30) {
            TrackOrderVo trackOrderVoo = new TrackOrderVo();
            trackOrderVoo.setTrackCount(30);
            trackOrderVoo.setPrice(price.multiply(new BigDecimal(30)));
            trackOrderVoo.setName("后30集");
            trackOrderVos.add(trackOrderVoo);
        }
        if (size > 50) {
            TrackOrderVo trackOrderVoo = new TrackOrderVo();
            trackOrderVoo.setTrackCount(50);
            trackOrderVoo.setPrice(price.multiply(new BigDecimal(50)));
            trackOrderVoo.setName("后50集");
            trackOrderVos.add(trackOrderVoo);
        }

        if (size > 1) {
            TrackOrderVo trackOrderVoo = new TrackOrderVo();
            trackOrderVoo.setTrackCount(size);
            trackOrderVoo.setPrice(price.multiply(new BigDecimal(size)));
            trackOrderVoo.setName("后" + size + "集");
            trackOrderVos.add(trackOrderVoo);
        }

        return trackOrderVos;
    }

    @Override
    public List<TrackInfo> findBuyTracks(Long trackId, Integer count) {
        //根据trackId查询声音信息
        TrackInfo trackInfo = this.trackInfoMapper.selectById(trackId);
        Assert.notNull(trackInfo, "查询购买声音列表时：查询声音信息失败！");
        //查询已购买的声音列表
        Result<List<UserPaidTrack>> payTrackResult = this.userInfoFeignClient.findPayTrack(trackInfo.getAlbumId());
        Assert.notNull(payTrackResult, "查询购买声音列表时：查询已购买声音失败！");
        List<UserPaidTrack> userPaidTracks = payTrackResult.getData();
        //查询购买的声音
        LambdaQueryWrapper<TrackInfo> queryWrapper = new LambdaQueryWrapper<TrackInfo>()
                .eq(TrackInfo::getAlbumId, trackInfo.getAlbumId())
                .ge(TrackInfo::getOrderNum, trackInfo.getOrderNum())
                .select(TrackInfo::getTrackTitle, TrackInfo::getCoverUrl, TrackInfo::getId)
                .last("limit " + count);
        //不为空，添加条件
        if (!CollectionUtils.isEmpty(userPaidTracks)) {
            List<Long> ids = userPaidTracks.stream().map(track -> track.getTrackId()).collect(Collectors.toList());
            queryWrapper.notIn(TrackInfo::getId, ids);
        }
        return this.list(queryWrapper);
    }
}
